package service

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"unicode/utf8"

	"github.com/androidsr/sc-go/sc"
	"github.com/androidsr/sc-go/scmd"
	"github.com/androidsr/sc-go/sno"
	"github.com/tmc/langchaingo/llms"
)

func ExecFuncCall(funcCall *llms.FunctionCall) (bool, string, error) {
	switch funcCall.Name {
	case "searchNetSource":
		//获取互联网内容
		return searchNetSource(funcCall.Arguments)
	case "getTables":
		//查询表结构
		return getTables(funcCall.Arguments)
	case "getTableDetail":
		//查询表详情
		return getTableDetail(funcCall.Arguments)
	case "queryExecSql":
		return queryExecSql(funcCall.Arguments)
	case "createPpt":
		return createPpt(funcCall.Arguments)
	}
	return false, "", errors.New("未找到对应的函数内容")
}

/** 获取数据库中所有表 **/
func getTables(arguments string) (bool, string, error) {
	input := make(map[string]string, 0)
	err := json.Unmarshal([]byte(arguments), &input)
	if err != nil {
		return true, "", errors.New("解析AI参数出错：" + err.Error())
	}
	dbname := input["dbname"]
	if dbname == "" {
		return true, "", errors.New("无效函数，未找到dbname参数")
	}
	info, err := NewDbDataSourceService().GetTables(dbname)
	if err != nil {
		log.Println("获取所有表信息出错")
		return true, "", errors.New("获取所有表信息出错")
	}
	bs, err := json.Marshal(info)
	if err != nil {
		return true, "", errors.New("表信息转换JSON出错：" + err.Error())
	}
	return false, string(bs), nil
}

/** 获取数据库表结构信息 **/
func getTableDetail(arguments string) (bool, string, error) {
	input := make(map[string]interface{}, 0)
	err := json.Unmarshal([]byte(arguments), &input)
	if err != nil {
		return true, "", errors.New("解析AI参数出错：" + err.Error())
	}
	dbname, ok := input["dbname"].(string)
	if !ok || dbname == "" {
		return true, "", errors.New("无效函数，未找到dbname参数")
	}
	tableNames, ok := input["tableNames"].([]interface{})
	if !ok {
		log.Println("转换数据不对", ok)
		return true, "", errors.New("无效函数，未找到tableNames参数")
	}
	log.Println("执行函数：", dbname, tableNames)
	data, err := NewDbDataSourceService().GetTableDetail(dbname, tableNames)
	return false, data, err
}

/** 获取数据库表结构信息 **/
func queryExecSql(arguments string) (bool, string, error) {
	input := make(map[string]string, 0)
	err := json.Unmarshal([]byte(arguments), &input)
	if err != nil {
		return true, "", errors.New("解析AI参数出错：" + err.Error())
	}
	dbname := input["dbname"]
	if dbname == "" {
		return true, "", errors.New("无效函数，未找到dbname参数")
	}
	sql := input["sql"]
	if sql == "" {
		return true, "", errors.New("无效函数，未找到tableName参数")
	}
	data, err := NewDbDataSourceService().QueryExecSql(dbname, sql)
	return true, data, err
}

/** 在线搜索信息 **/
func searchNetSource(arguments string) (bool, string, error) {
	input := make(map[string]string, 0)
	err := json.Unmarshal([]byte(arguments), &input)
	if err != nil {
		return true, "", errors.New("解析AI参数出错：" + err.Error())
	}
	url := input["url"]
	if url == "" {
		return true, "", errors.New("无效函数，未找到url参数")
	}
	content := input["content"]
	if url == "" {
		return true, "", errors.New("无效函数，未找到url参数")
	}

	if content != "" {
		url += content
	}

	buf := bytes.Buffer{}
	web := NewChromedp()
	defer web.Close()

	cfg := NewCrawlerSelecterService().GetDomainInfo(url, "link")
	var selecter string
	if cfg == nil {
		selecter = "a"
	} else {
		selecter = cfg.LinkSelecter
	}
	links := web.GetLink(url, selecter)
	if links == nil {
		return false, "", nil
	}
	for _, v := range links {
		cfg := NewCrawlerSelecterService().GetDomainInfo(url, "content")
		if cfg == nil {
			selecter = "body"
		} else {
			selecter = cfg.TextSelecter
		}
		text, err := web.GetContent(v, selecter)
		if err != nil {
			log.Printf("获取文档内容处理失败：%s", err.Error())
			continue
		}
		tmp := bytes.NewBufferString(text)
		for {
			line, err := tmp.ReadString('\n')
			if err != nil {
				break
			}
			if line == "" || utf8.RuneCountInString(line) <= 8 {
				continue
			}
			buf.WriteString(line)
		}
	}
	return true, buf.String(), nil
}

/** 创建PPT文件 **/
func createPpt(arguments string) (bool, string, error) {
	fmt.Println(arguments)
	input := make(map[string]string, 0)
	err := json.Unmarshal([]byte(arguments), &input)
	if err != nil {
		return true, "", errors.New("解析AI参数出错：" + err.Error())
	}
	template := input["template"]
	if template == "" {
		return true, "", errors.New("无效函数，未找到template参数")
	}
	tempInfo := NewPptTemplateService().Get(template)
	if tempInfo == nil {
		return true, "", errors.New("无效的模板，未找到template参数")
	}
	data := input["jsonData"]
	if data == "" {
		return true, "", errors.New("无效函数，未找到jsonData参数")
	}
	//data = strings.ReplaceAll(data, "\\", "")
	cmd := scmd.New(func(shell, output string) bool {
		log.Println(shell, output)
		return true
	})

	name := sno.GetString() + ".pptx"
	newFilename := "temp/" + name
	err = cmd.Command("java -jar ./extlib/ai-pptx.jar " + tempInfo.FilePath + " " + newFilename + " " + base64.StdEncoding.EncodeToString([]byte(data)))
	if err != nil {
		return false, "", err
	}
	if !sc.IsFile(newFilename) {
		return true, "", errors.New("找出这个JSON格式中的错误并修改后重新输出")
	}
	resultData := make(map[string]string, 0)
	resultData["actionType"] = "download"
	resultData["filename"] = name
	bs, _ := json.Marshal(resultData)
	return false, string(bs), nil
}
